package znet

import (
	"fmt"
	"zinx/utils"
	"zinx/ziface"
)

type MsgHandler struct {
	// 存放每个MsgID 所对应的处理方法
	Apis map[uint32]ziface.IRouter

	WorkerPoolSize uint32
	TaskQueue      []chan ziface.IRequest
}

func NewMsgHandler() *MsgHandler {
	return &MsgHandler{
		Apis:           make(map[uint32]ziface.IRouter),
		WorkerPoolSize: utils.GlobalObject.WorkerPoolSize,
		TaskQueue:      make([]chan ziface.IRequest, utils.GlobalObject.WorkerPoolSize),
	}
}

// DoMsgHandler 调度、执行对应的Router消息处理方法
func (mh *MsgHandler) DoMsgHandler(request ziface.IRequest) {
	handler, ok := mh.Apis[request.GetMsgId()]
	if !ok {
		fmt.Println("api msgID ", request.GetMsgId(), " is not found need register")
		return
	}
	handler.PreHandle(request)
	handler.Handle(request)
	handler.PostHandle(request)
}

// AddRouter 为消息添加具体的处理逻辑
func (mh *MsgHandler) AddRouter(msgID uint32, router ziface.IRouter) {
	// 判断当前msg绑定的API处理方法是否已经存在
	if _, ok := mh.Apis[msgID]; ok {
		fmt.Println("current msgID ", msgID, " has exited")
		return
	}

	// 添加绑定关系
	mh.Apis[msgID] = router
}

// StartWorkerPool 启动一个Worker工作池 (只能发生一次)
func (mh *MsgHandler) StartWorkerPool() {
	for i := 0; i < int(mh.WorkerPoolSize); i++ {
		mh.TaskQueue[i] = make(chan ziface.IRequest, utils.GlobalObject.MaxWorkerTaskLen)
		go mh.startOneWorker(i, mh.TaskQueue[i])
	}
}

// StartOneWorker 启动一个Worker工作流程
func (mh *MsgHandler) startOneWorker(workerID int, taskQue chan ziface.IRequest) {
	fmt.Println("Worker ID = ", workerID, " is started...")

	for {
		select {
		case request := <-taskQue:
			mh.DoMsgHandler(request)
		}
	}
}

// SendMsgToTaskQueue 将消息交给TaskQueue
func (mh *MsgHandler) SendMsgToTaskQueue(request ziface.IRequest) {
	workerID := request.GetConnection().GetConnId() % mh.WorkerPoolSize
	fmt.Println("Add ConnId = ", request.GetConnection().GetConnId(), " request MsgID = ", request.GetMsgId(),
		" to WorkerID = ", workerID)

	mh.TaskQueue[workerID] <- request
}
